package com.ruoyi.flowable.listener.repair;

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.data.RowRenderData;
import com.deepoove.poi.data.Rows;
import com.deepoove.poi.data.Tables;
import com.deepoove.poi.policy.PictureRenderPolicy;
import com.deepoove.poi.policy.TableRenderPolicy;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.equ.domain.EquRepair;
import com.ruoyi.equ.service.IEquRepairService;
import com.ruoyi.flowable.domain.WorkOrderAssetRel;
import com.ruoyi.flowable.service.IWorkOrderAssetRelService;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import org.springframework.stereotype.Component;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static com.ruoyi.flowable.listener.asset.AssetCompleteListener.*;
import static com.ruoyi.flowable.listener.repair.RepairExecutionListener.getRepairTime;

/**
 * 维修-完成监听
 */
@Slf4j
@Component("repairCompleteListener")
public class RepairCompleteListener implements ExecutionListener {
    private static final ObjectMapper objectMapper = new ObjectMapper();
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static final IEquRepairService repairService = SpringUtils.getBean(IEquRepairService.class);
    private static final IWorkOrderAssetRelService workOrderAssetRelService = SpringUtils.getBean(IWorkOrderAssetRelService.class);


    @Override
    public void notify(DelegateExecution execution) {
        try {
            //工单最终状态:已完成
            String orderStatus = "已完成";

            //工单闭环时间
            Date closeTime = sdf.parse(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

            //updateBy
            String updateBy = SecurityUtils.getLoginUser().getUser().getNickName();

            EquRepair equRepair = execution.getVariable("equRepair", EquRepair.class);
//            equRepair.setRepairCheck(repairCheck);
            equRepair.setOrderStatus(orderStatus);
            equRepair.setCloseTime(closeTime);
            equRepair.setUpdateBy(updateBy);

            //修改
            repairService.updateEquRepair(equRepair);
            //json
            execution.setVariable("equRepair", equRepair);

            //更新状态
            String processInstanceId = execution.getProcessInstanceId();
            WorkOrderAssetRel workOrderAssetRel = new WorkOrderAssetRel();
            workOrderAssetRel.setProcInsId(processInstanceId);
            workOrderAssetRel.setWorkOrderStatus("已完成");
            workOrderAssetRel.setFinishTime(new Date());
            //生成word
            String url = generateWord(execution.getVariables(), equRepair);
            workOrderAssetRel.setFileUrl(url);
            workOrderAssetRelService.updateWorkOrderAssetRel(workOrderAssetRel);
        } catch (ParseException | IOException e) {
            throw new RuntimeException(e);
        }
    }

    private String generateWord(Map<String, Object> variables, EquRepair equRepair) throws IOException, ParseException {
        BufferedInputStream resourceAsStream = new BufferedInputStream(
                Objects.requireNonNull(this.getClass().getClassLoader().getResourceAsStream("word/医院设备维修工单.docx"))
        );
        // 使用配置编译模板
        XWPFTemplate template = XWPFTemplate.compile(resourceAsStream);
        Configure config = template.getConfig();

        HashMap<String, Object> finalMap = new HashMap<>();
        finalMap.put("工单编号", equRepair.getRepairId());//repair_id
        //'待派工','已完成','维修中'
        String orderStatus = equRepair.getOrderStatus();
        //☑ 待派工 □ 维修中 □ 待验收 □ 已完成 □ 已终止
        if (orderStatus.equals("待派工")) {
            finalMap.put("工单状态", "☑ 待派工 □ 维修中 □ 已完成");
        } else if (orderStatus.equals("维修中")) {
            finalMap.put("工单状态", "□ 待派工 ☑ 维修中 □ 已完成");
        } else if (orderStatus.equals("已完成")) {
            finalMap.put("工单状态", "□ 待派工 □ 维修中 ☑ 已完成");
        }
        finalMap.put("创建日期", sdf.format(equRepair.getCreateTime()));

        finalMap.put("报修科室", variables.get("repairDept"));
        finalMap.put("报修人", variables.get("repairPerson"));
        finalMap.put("联系电话", variables.get("phone"));
        finalMap.put("设备使用地点", variables.get("location"));
        String urgency = variables.get("urgency").toString();
        if (urgency.equals("紧急")) {
            finalMap.put("紧急程度", "☑ 紧急（影响急诊 / 重症诊疗，需 2 小时内响应）\n" +
                    "□ 一般（影响常规诊疗，需 24 小时内响应）\n" +
                    "□ 普通（不影响核心诊疗，需 48 小时内响应）\n");
        } else if (urgency.equals("一般")) {
            finalMap.put("紧急程度", "□ 紧急（影响急诊 / 重症诊疗，需 2 小时内响应）\n" +
                    "☑ 一般（影响常规诊疗，需 24 小时内响应）\n" +
                    "□ 普通（不影响核心诊疗，需 48 小时内响应）\n");
        } else if (urgency.equals("普通")) {
            finalMap.put("紧急程度", "□ 紧急（影响急诊 / 重症诊疗，需 2 小时内响应）\n" +
                    "□ 一般（影响常规诊疗，需 24 小时内响应）\n" +
                    "☑ 普通（不影响核心诊疗，需 48 小时内响应）\n");
        }

        finalMap.put("设备名称", variables.get("assetName"));
        finalMap.put("设备型号规格", variables.get("modelSpec"));
        finalMap.put("资产编号", variables.get("assetNumber"));
        finalMap.put("生产厂家", variables.get("manufacturer"));
        finalMap.put("厂家联系方式", variables.get("manufacturerPhone"));
        finalMap.put("购置日期", variables.get("purchaseDate"));
        finalMap.put("已使用时长", variables.get("actualServiceTime"));
        finalMap.put("上次维修日期", variables.get("lastRepairDate"));
        finalMap.put("上次维修内容", variables.get("lastRepairContent"));

        finalMap.put("故障发生时间", variables.get("faultTime"));
        List<Map<String, String>> faultFiles = (List<Map<String, String>>) variables.get("faultFiles");
        for (int i = 0; i < faultFiles.size(); i++) {
            String fileUrl = faultFiles.get(i).get("url");
            String fileName = fileUrl.toLowerCase();
            // 使用正则表达式匹配图片文件
            if (fileName.matches(".*\\.(jpg|jpeg|png|gif|bmp|tiff|tif|webp|svg)$")) {
                finalMap.put("故障现象图片" + (i + 1), Pictures.ofLocal(replaceUrl(fileUrl)).size(200, 80).create());
                config.customPolicy("故障现象图片" + (i + 1), new PictureRenderPolicy());
            }
        }

        String faultType = variables.get("faultType").toString();
        if (faultType.equals("无法开机")) {
            finalMap.put("故障现象", "☑ 无法开机 / 启动异常 □ 运行中报错\n" +
                    "□ 性能下降（如：检测精度偏差、速度变慢） □ 部件损坏\n" +
                    "□ 异响 / 异味 □ 其他");
        } else if (faultType.equals("运行报错")) {
            finalMap.put("故障现象", "□ 无法开机 / 启动异常 ☑ 运行中报错（错误代码：" + variables.get("errorCode") + "）\n" +
                    "□ 性能下降（如：检测精度偏差、速度变慢） □ 部件损坏\n" +
                    "□ 异响 / 异味 □ 其他");
        } else if (faultType.equals("性能下降")) {
            finalMap.put("故障现象", "□ 无法开机 / 启动异常 □ 运行中报错\n" +
                    "☑ 性能下降（如：检测精度偏差、速度变慢） □ 部件损坏\n" +
                    "□ 异响 / 异味 □ 其他");
        } else if (faultType.equals("部件损坏")) {
            finalMap.put("故障现象", "□ 无法开机 / 启动异常 □ 运行中报错\n" +
                    "□ 性能下降（如：检测精度偏差、速度变慢） ☑ 部件损坏（损坏部件：" + variables.get("componentName") + "）\n" +
                    "□ 异响 / 异味 □ 其他");
        } else if (faultType.equals("异响/异味")) {
            finalMap.put("故障现象", "□ 无法开机 / 启动异常 □ 运行中报错\n" +
                    "□ 性能下降（如：检测精度偏差、速度变慢） □ 部件损坏\n" +
                    "☑ 异响 / 异味 □ 其他");
        } else if (faultType.equals("其他")) {
            finalMap.put("故障现象", "□ 无法开机 / 启动异常 □ 运行中报错\n" +
                    "□ 性能下降（如：检测精度偏差、速度变慢） □ 部件损坏\n" +
                    "□ 异响 / 异味 ☑ 其他");
        }

        String faultImpact = variables.get("faultImpact").toString();
        if (faultImpact.equals("单个诊疗项目")) {
            finalMap.put("故障影响范围1", "☑");
            finalMap.put("故障影响范围2", "□");
            finalMap.put("故障影响范围3", "□");
            finalMap.put("故障影响范围4", "□");
        } else if (faultImpact.equals("科室部分业务")) {
            finalMap.put("故障影响范围1", "□");
            finalMap.put("故障影响范围2", "☑");
            finalMap.put("故障影响范围3", "□");
            finalMap.put("故障影响范围4", "□");
        } else if (faultImpact.equals("科室整体诊疗")) {
            finalMap.put("故障影响范围1", "□");
            finalMap.put("故障影响范围2", "□");
            finalMap.put("故障影响范围3", "☑");
            finalMap.put("故障影响范围4", "□");
        } else if (faultImpact.equals("无影响")) {
            finalMap.put("故障影响范围1", "□");
            finalMap.put("故障影响范围2", "□");
            finalMap.put("故障影响范围3", "□");
            finalMap.put("故障影响范围4", "☑");
        }

        List<String> specialDemand = (List<String>) variables.get("specialDemand");
        if (specialDemand.contains("需备用设备")) {
            finalMap.put("特殊需求", "☑ 需提供备用设备（备用设备型号 / 需求：" + variables.get("spareDeviceModel") + "）\n" +
                    "□ 维修后需现场校准 / 检测 □ 需提交维修报告（含部件更换清单）");
        } else if (specialDemand.contains("维修后校准")) {
            finalMap.put("特殊需求", "□ 需提供备用设备\n" +
                    "☑ 维修后需现场校准 / 检测 □ 需提交维修报告（含部件更换清单）");
        } else if (specialDemand.contains("提交维修报告")) {
            finalMap.put("特殊需求", "□ 需提供备用设备\n" +
                    "□ 维修后需现场校准 / 检测 ☑ 需提交维修报告（含部件更换清单）");
        }

        finalMap.put("派工部门", variables.get("assignDept"));
        finalMap.put("维修负责人", variables.get("leader"));
        finalMap.put("维修负责人联系电话", variables.get("leaderPhone"));
        finalMap.put("派工日期", variables.get("assignDate"));
        finalMap.put("预计完成时间", variables.get("willTime"));

        finalMap.put("故障位置", variables.get("wrongLocation"));
        finalMap.put("初步判断", variables.get("firstConfirm"));

        List<String> wrongReason = (List<String>) variables.get("wrongReason");

        //□ 部件老化损坏（损坏部件：xxx） □ 操作不当 □ 环境因素（如：湿度 / 电压异常）□ 软件故障 □ 其他：xxx
        if (wrongReason.contains("部件老化损坏")) finalMap.put("故障原因1", "☑ 部件老化损坏");
        else finalMap.put("故障原因1", "□ 部件老化损坏");
        if (wrongReason.contains("操作不当")) finalMap.put("故障原因2", "☑");
        else finalMap.put("故障原因2", "□");
        if (wrongReason.contains("环境因素")) finalMap.put("故障原因3", "☑");
        else finalMap.put("故障原因3", "□");
        if (wrongReason.contains("软件故障")) finalMap.put("故障原因4", "☑");
        else finalMap.put("故障原因4", "□");
        if (wrongReason.contains("其他")) finalMap.put("故障原因5", "☑ 其他");
        else finalMap.put("故障原因5", "□ 其他");

        //TODO 维修图片
//        finalMap.put("维修图片", Pictures.ofUrl("http://192.168.10.85:9600/profile/upload/2025/11/22/aaa_20251122202027A001.png").center().size(200, 80).create());
//        "维修措施实施", "□ 部件更换（更换部件型号 / 数量：xxx）\n" +
//                "□ 设备清洁校准 □ 软件调试 / 升级 □ 线路检修 □ 其他：xxx"
        String repairStep = variables.get("repairStep").toString();
        if (repairStep.contains("部件更换")) finalMap.put("维修措施实施1", "☑ 部件更换");
        else finalMap.put("维修措施实施1", "□ 部件更换");
        if (repairStep.contains("清洁校准")) finalMap.put("维修措施实施2", "☑");
        else finalMap.put("维修措施实施2", "□");
        if (repairStep.contains("软件调试")) finalMap.put("维修措施实施3", "☑");
        else finalMap.put("维修措施实施3", "□");
        if (repairStep.contains("线路检修")) finalMap.put("维修措施实施4", "☑");
        else finalMap.put("维修措施实施4", "□");
        if (repairStep.contains("其他")) finalMap.put("维修措施实施5", "☑ 其他");
        else finalMap.put("维修措施实施5", "□ 其他");

        //表格
        RowRenderData rowRenderData = Rows.of("材料 / 部件名称", "型号规格", "数量", "单价（元）", "金额（元）", "供应商").textBold().create();
        Tables.TableBuilder tableBuilder = Tables.of(rowRenderData);
        List<Map<String, Object>> materialSubForm = (List<Map<String, Object>>) variables.get("materialSubForm");
        for (int i = 0; i < materialSubForm.size(); i++) {
            tableBuilder.addRow(Rows.of(materialSubForm.get(i).get("materialName").toString(),
                    materialSubForm.get(i).get("modelSpec").toString(),
                    materialSubForm.get(i).get("quantity").toString(),
                    materialSubForm.get(i).get("unitPrice").toString(),
                    materialSubForm.get(i).get("amount").toString(),
                    materialSubForm.get(i).get("supplier").toString()).center().create());
        }
        tableBuilder.addRow(Rows.of("合计金额（元）", "——", "——", "——", variables.get("allAmount").toString(), "——").create());
        finalMap.put("表格", tableBuilder.create());
        config.customPolicy("表格", new TableRenderPolicy());

        List<String> repairTime = (List<String>) variables.get("repairTime");
        finalMap.put("开始时间", repairTime.get(0));
        finalMap.put("结束时间", repairTime.get(1));
        finalMap.put("实际维修时长", getRepairTime(repairTime));

        String  flag4_1 = variables.get("flag4_1").toString();
        String flag4_2 = variables.get("flag4_2").toString();
        String flag4_3 = variables.get("flag4_3").toString();
        if (flag4_1.equals("设备运行正常，性能达标")) finalMap.put("维修部门自检1", "☑");
        else finalMap.put("维修部门自检1", "□");
        if (flag4_2.equals("维修部位无异常")) finalMap.put("维修部门自检2", "☑");
        else finalMap.put("维修部门自检2", "□");
        if (flag4_3.equals("现场清理完毕")) finalMap.put("维修部门自检3", "☑");
        else finalMap.put("维修部门自检3", "□");

        //signature_act0_4
        List<Map<String, String>> signature_act0_4 = (List<Map<String, String>>) variables.get("signature_act0_4");
        finalMap.put("维修部门自检人签字", Pictures.ofLocal(replaceUrl(signature_act0_4.get(0).get("url"))).size(200, 80).create());
        config.customPolicy("维修部门自检人签字", new PictureRenderPolicy());
        finalMap.put("维修部门自检人签字日期", variables.get("date4_4"));

        String flag5_1 = variables.get("flag5_1").toString();
        String flag5_2 = variables.get("flag5_2").toString();
        String manyi = variables.get("manyi").toString();
        if (flag5_1.equals("故障已解决")) finalMap.put("验收内容1", "☑");
        else finalMap.put("验收内容1", "□");
        if (flag5_2.equals("设备运行符合使用要求")) finalMap.put("验收内容2", "☑");
        else finalMap.put("验收内容2", "□");

        if (manyi.equals("满意")) finalMap.put("满意", "☑ 满意 □ 基本满意 □ 不满意");
        else if (manyi.equals("基本满意")) finalMap.put("满意", "□ 满意 ☑ 基本满意 □ 不满意");
        else if (manyi.equals("不满意")) finalMap.put("满意", "□ 满意 □ 基本满意 ☑ 不满意（原因："+variables.get("reason5_1")+"）");

        List<Map<String, String>> signature_act0_5 = (List<Map<String, String>>) variables.get("signature_act0_5");
        finalMap.put("验收人签字", Pictures.ofLocal(replaceUrl(signature_act0_5.get(0).get("url"))).size(200, 80).create());
        config.customPolicy("验收人签字", new PictureRenderPolicy());
        List<Map<String, String>> leaderSign_act0_5 = (List<Map<String, String>>) variables.get("leaderSign_act0_5");
        finalMap.put("科室负责人签字", Pictures.ofLocal(replaceUrl(leaderSign_act0_5.get(0).get("url"))).size(200, 80).create());
        config.customPolicy("科室负责人签字", new PictureRenderPolicy());
        finalMap.put("验收日期", variables.get("date5_5"));

        //财务
        String flag6 = variables.get("flag6").toString();
        if (StringUtils.isNotEmpty(flag6)) {
            finalMap.put("财务内容", "\n3. 财务 / 资产管理部门确认");

            if (flag6.equals("费用无误")) {
                finalMap.put("财务确认", "\n☑ 维修费用核对无误 □ 部件更换记录已存档");
            }
            else if (flag6.equals("费用有误")) {
                finalMap.put("财务确认", "\n□ 维修费用核对无误 ☑ 部件更换记录已存档");
            }

            finalMap.put("签字内容", "\n确认人签字：");
            List<Map<String, String>> signature_act0_6 = (List<Map<String, String>>) variables.get("signature_act0_6");
            finalMap.put("确认人签字", Pictures.ofLocal(replaceUrl(signature_act0_6.get(0).get("url"))).size(200, 80).create());
            config.customPolicy("确认人签字", new PictureRenderPolicy());
            finalMap.put("签字日期内容", "\n日期：");
            finalMap.put("确认人签字日期", variables.get("date6_6"));
        }

        template.render(finalMap);
        // 生成临时文件
        String tempFileName = "设备维修单_" + variables.get("assetNumber") + "_" + System.currentTimeMillis() + ".docx";
        File tempFile = new File(System.getProperty("java.io.tmpdir"), tempFileName);

        try {
            template.writeToFile(tempFile.getAbsolutePath());
            log.info("Word文档生成成功，临时文件路径: {}", tempFile.getAbsolutePath());
            // 上传文件
            return uploadWordFile(tempFile, tempFileName);
            //本地路径
//            String wordPath = "D:\\项目学习\\若依工作流\\word\\aa.docx";
//            template.writeToFile(wordPath);
//            System.out.println("Word文档生成成功！");
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            template.close();
            resourceAsStream.close();
        }
    }
}
